#include "udp_sender.h"
#include "baseFilter.h"
#include <boost/algorithm/string.hpp>

class TcpFilter : public BaseFilter
{
public:
	TcpFilter(com::Subscription const& subscription):m_port(0), m_src_port(0), m_dst_port(0)
	{

		if(subscription.has_port())
			m_port = htons(subscription.port());

		if(subscription.has_src_port())
			m_src_port = htons(subscription.src_port());

		if(subscription.has_dst_port())
			m_dst_port = htons(subscription.dst_port());
	}
	bool tcp_port_validate(Frame const& frame)
	{
		if(m_dst_port && ! (frame.getTCP()->th_dport == m_dst_port))
			return false;

		if(m_src_port && ! (frame.getTCP()->th_sport == m_src_port))
			return false;

		if(m_port && ! (frame.getTCP()->th_sport == m_port || frame.getTCP()->th_dport == m_port))
			return false;

		return true;
	}
private:
	u_short m_port;
	u_short m_src_port;
	u_short m_dst_port;
};


class HttpFilter : public TcpFilter
{
	const u_int findNewLine(const char* content, const u_int len)
	{
		for(u_int i=0; i <= len; ++i)
		{
			if(content[i] == '\n')
				return i;
		}
		return 0;
	}
public:
	HttpFilter(com::Subscription const& subscription): TcpFilter(subscription)
	{
		com::Http const& http = subscription.http();

		if(http.has_url())
			m_subUrl = http.url();

		if(http.has_httprequesttype())
			m_httpRequestType = http.httprequesttype();
		if(http.has_urlsearchpos())
			m_url_search_position = http.urlsearchpos();
	}
	bool validate(Frame const& frame)
	{
		if( ! tcp_port_validate(frame))
			return false;

		if(frame.getCharPayloadLen() < m_httpRequestType.size())
			return false;

		if(strncmp(m_httpRequestType.c_str(), frame.getCharPayload(), m_httpRequestType.size()))
			return false;

		/*			std::string httpType(frame.getPayload(m_httpRequestType.size()));

		                        if(! m_httpRequestType.empty() && ! boost::algorithm::starts_with(httpType, m_httpRequestType))
						return false;
		*/
		if(! m_subUrl.empty())
		{
			u_int newline = findNewLine(frame.getCharPayload(), frame.getCharPayloadLen());

			std::string content(frame.getPayload(newline));

			switch(m_url_search_position)
			{
			case com::Http_Url_search_position_SUB:
				if(! boost::algorithm::contains(content, m_subUrl))
					return false;
				break;
			case com::Http_Url_search_position_START:
				if(! boost::algorithm::starts_with(content, m_subUrl))
					return false;
				break;
			case com::Http_Url_search_position_END:
				if(! boost::algorithm::ends_with(content, m_subUrl))
					return false;
				break;
			default:
				if(! boost::algorithm::contains(content, m_subUrl))
					return false;
			}

		}
		return true;
	}
private:
	std::string m_subUrl;
	std::string m_httpRequestType;
	int m_url_search_position;
};

BaseFilterPointer createFilter(com::Subscription const& subscription)
{
	if(subscription.has_http())
		return BaseFilterPointer(new HttpFilter(subscription));

	return BaseFilterPointer();
}

